﻿using DNFImagePacks2Manager.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace DNFImagePacks2Manager.Helpers
{

    public sealed class NPKListHelper
    {

        public static List<NPKItemBase> GetOfficialNPKList()
        {
            List<NPKItemBase> list = [];
            if (LocalStorageHelper.IsSetDNFPath()) {
                string imagePath = LocalStorageHelper.GetImagePath();
                if (Directory.Exists(imagePath))
                {
                    foreach (string filePath in Directory.EnumerateFiles(imagePath))
                    {
                        string fileName = Path.GetFileName(filePath);
                        if (!NPKHelper.FilenameCheckImageOfficial(fileName))
                        {
                            continue;
                        }

                        NPKItemBase npkItem = new NPKItemImageOfficial(fileName, imagePath);
                        list.Add(npkItem);
                    }
                }
                string soundPath = LocalStorageHelper.GetSoundPath();
                if (Directory.Exists(soundPath))
                {
                    foreach (string filePath in Directory.EnumerateFiles(soundPath))
                    {
                        string fileName = Path.GetFileName(filePath);
                        if (!NPKHelper.FilenameCheckSoundOfficial(fileName))
                        {
                            continue;
                        }

                        NPKItemBase npkItem = new NPKItemSoundOfficial(fileName, soundPath);
                        list.Add(npkItem);
                    }
                }
            }
            return list;
        }
        public static List<NPKItemBase> GetAllList(out int enabledCount)
        {
            var allItems = new List<NPKItemBase>();

            var soundItems = GetSoundList(out int soundEnabledCount);
            var npkItems = GetImageList(out int npkEnabledCount);
            allItems.AddRange(soundItems);
            allItems.AddRange(npkItems);

            enabledCount = npkEnabledCount + soundEnabledCount;
            return allItems;
        }

        public static List<NPKItemBase> GetImageList(out int enabledCount)
        {
            return GetFilteredNPKList(
                pathGetter: LocalStorageHelper.GetImagePath,
                nameChecker: NPKHelper.FilenameCheckImage,
                itemFactory: (fileName, path) => new NPKItemImage(fileName, path),
                filter: _ => true,
                enabledCount: out enabledCount
            );
        }

        public static List<NPKItemBase> GetSoundList(out int enabledCount)
        {
            return GetFilteredNPKList(
                pathGetter: LocalStorageHelper.GetSoundPath,
                nameChecker: NPKHelper.FilenameCheckSound,
                itemFactory: (fileName, path) => new NPKItemSound(fileName, path),
                filter: _ => true,
                enabledCount: out enabledCount
            );
        }

        public static List<NPKItemBase> GetEnabledAllList()
        {
            var enabledItems = new List<NPKItemBase>();
            enabledItems.AddRange(GetEnabledSoundList());
            enabledItems.AddRange(GetEnabledImageList());
            return enabledItems;
        }

        public static List<NPKItemBase> GetEnabledImageList()
        {
            return GetFilteredNPKList(
                pathGetter: LocalStorageHelper.GetImagePath,
                nameChecker: NPKHelper.FilenameCheckImage,
                itemFactory: (fileName, path) => new NPKItemImage(fileName, path),
                filter: item => item.Status
            );
        }

        public static List<NPKItemBase> GetEnabledSoundList()
        {
            return GetFilteredNPKList(
                pathGetter: LocalStorageHelper.GetSoundPath,
                nameChecker: NPKHelper.FilenameCheckSound,
                itemFactory: (fileName, path) => new NPKItemSound(fileName, path),
                filter: item => item.Status
            );
        }

        private static List<NPKItemBase> GetFilteredNPKList(
            Func<string> pathGetter,
            Func<string, bool> nameChecker,
            Func<string, string, NPKItemBase> itemFactory,
            Func<NPKItemBase, bool> filter,
            out int enabledCount)
        {
            enabledCount = 0;
            var filteredItems = new List<NPKItemBase>();

            try
            {
                string targetPath = pathGetter();
                if (string.IsNullOrWhiteSpace(targetPath))
                {
                    return filteredItems;
                }

                if (!Directory.Exists(targetPath))
                {
                    return filteredItems;
                }

                foreach (string filePath in Directory.EnumerateFiles(targetPath))
                {
                    string fileName = Path.GetFileName(filePath);
                    if (!nameChecker(fileName))
                    {
                        continue;
                    }

                    NPKItemBase npkItem = itemFactory(fileName, targetPath);
                    npkItem.UpdateStatus();
                    if (npkItem.Status)
                    {
                        enabledCount++;
                    }

                    if (filter(npkItem))
                    {
                        filteredItems.Add(npkItem);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return filteredItems;
        }

        private static List<NPKItemBase> GetFilteredNPKList(
            Func<string> pathGetter,
            Func<string, bool> nameChecker,
            Func<string, string, NPKItemBase> itemFactory,
            Func<NPKItemBase, bool> filter)
        {
            return GetFilteredNPKList(pathGetter, nameChecker, itemFactory, filter, out _);
        }
    }
}